﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EntitiesLayer;
using System.Transactions;
using System.Data.SqlClient;
using System.Data;
using System.Drawing;
using System.IO;

namespace DAL.Repositories
{
    class MissionRepository : IRepository<Mission>
    {
        private IList<IEntity> insertedList;
        private IList<IEntity> updatedList;
        private IList<IEntity> deletedList;

        internal MissionRepository()
        {

            insertedList = new List<IEntity>();
            updatedList = new List<IEntity>();
            deletedList = new List<IEntity>();
        }

        public void Insert(Mission entity)
        {
            insertedList.Add(entity);
        }

        public void Delete(Mission entity)
        {
            throw new NotImplementedException();
            //deletedList.Add(entity);
        }

        public void Update(Mission entity)
        {
            throw new NotImplementedException();
            //updatedList.Add(entity);
        }

        public IEnumerable<Mission> GetAll()
        {
          
            SqlCommand cmd = new SqlCommand();
            DataSet ds = DBAccess.ExecuteSPWithDS(ref cmd, "pa_listar_missiones");

            foreach (DataRow dr in ds.Tables[0].Rows)
                yield return crearMission(dr,Convert.ToInt32( dr["IDMISION"]));

        }

        public Mission GetById(int id)
        {

            Mission objMission = null;
            SqlCommand cmd = new SqlCommand();
            cmd.Parameters.Add(new SqlParameter("@IdMision", id));
            DataSet ds = DBAccess.ExecuteSPWithDS(ref cmd, "pa_consultar_mission_porID ");
             

            foreach (DataRow dr in ds.Tables[0].Rows)
                 objMission= crearMission(dr,id);

            return objMission;
        }

        public void Save()
        {
            using (TransactionScope scope = new TransactionScope())
            {

                try
                {

                    foreach (Mission p in insertedList)
                        InsertSatelite(p);

                    foreach (Mission p in updatedList)
                        UpdateSatelite(p);

                    foreach (Mission p in deletedList)
                        DeleteSatelite(p);


                    scope.Complete();
                }
                catch (TransactionAbortedException ex)
                {
                    Console.WriteLine(ex.Message);
                    throw ex;
                }
                catch (ApplicationException ex)
                {
                    Console.WriteLine(ex.Message);
                    throw ex;
                }
                finally
                {
                    Clear();
                }

            }
        }

        public void Clear()
        {
            insertedList.Clear();
            updatedList.Clear();
            deletedList.Clear();
        }
        #region Utilities

        internal static Mission crearMission(DataRow dr, int id) { 
           Bitmap insignia=null;



               byte[] b = (byte[])dr["INSIGNIA"];
               
              if (b.Length>0)
               {

                   using (var ms = new MemoryStream((byte[])dr["INSIGNIA"]))
                   {
                       //ArgumentException capturar la excepcion en el gestor
                       try
                       {

                           insignia = new Bitmap(ms);
                       }
                       catch (ArgumentException ex) {
                           Console.WriteLine(ex.Message);
                       }
                   }
               }
           
            int idCuerpo = Convert.ToInt32(dr["IDCUERPODESTINO"]);
            int idPrograma = Convert.ToInt32(dr["IDPROGRAMA"]);
                
            Mission objMission=new Mission(
                                
                                id: id,      
                                nombre: dr["NOMBRE"].ToString(),
                                tripulantes: dr["TRIPULANTES"].ToString(),
                                fechaLanzamiento: Convert.ToDateTime(dr["FECLANZAMIENTO"]),
                                duracion: new TimeSpan(Convert.ToInt64(dr["DURACION"])),
                                datosInteres: dr["DATOSINTERES"].ToString(),
                                resultado: dr["RESULTADO"].ToString(),
                                insignia: insignia,
                                nave: dr["NAVE"].ToString(),
                                idCuerpoCeleste: idCuerpo,
                                idProgramaEspacial: idPrograma,
                                lazyDelegateCuerpo: new Lazy<CuerpoCeleste>(()=>{
                                    return UnitOfWork.CuerpoCelesteRepository.GetById(idCuerpo);
                                }),
                                
                                lazyDelegatePrograma: new Lazy<ProgramaEspacial>(()=>{
                                    return UnitOfWork.ProgramaRespository.GetById(idPrograma);
                                }) 

                    
                    );


          return objMission;
        }

           
        

        private void InsertSatelite(Mission objMission)
        {
            try
            {

                ImageConverter convertidor = new ImageConverter();
                    byte[] imagen= (byte[])convertidor.ConvertTo(objMission.Insignia, typeof(byte[]));
                
                SqlCommand cmd = new SqlCommand();
                cmd.Parameters.Add(new SqlParameter("@idprograma", objMission.IdProgramaEspacial));
                cmd.Parameters.Add(new SqlParameter("@nombre", objMission.Nombre));
                cmd.Parameters.Add(new SqlParameter("@tripulantes", objMission.Tripulantes));
                cmd.Parameters.Add(new SqlParameter("@feclanza", objMission.FechaLanzamiento));
                cmd.Parameters.Add(new SqlParameter("@duracion", objMission.Duracion.Ticks));
                cmd.Parameters.Add(new SqlParameter("@datos", objMission.DatosInteres));
                cmd.Parameters.Add(new SqlParameter("@resultado", objMission.Resultado));
                cmd.Parameters.Add(new SqlParameter("@insignia",imagen ));
                cmd.Parameters.Add(new SqlParameter("@nave", objMission.Nave));
                cmd.Parameters.Add(new SqlParameter("@iddestino", objMission.IdCuerpoCeleste));
                DataSet ds = DBAccess.ExecuteSPWithDS(ref cmd, "pa_RegistrarMision");
                  
                
            }
            catch (SqlException ex)
            {
                Console.WriteLine(ex.Message);
                throw ex;
            }

        }

        private void UpdateSatelite(Mission objSatelite)
        {
            throw new NotImplementedException();

        }

        private void DeleteSatelite(Mission objSatelite)
        {
            throw new NotImplementedException();

        }

        internal static IList<Mission> consultarMissionesPrograma(int idPrograma){
        
            IList<Mission> missiones = new List<Mission>();
            SqlCommand cmd = new SqlCommand();
            cmd.Parameters.Add(new SqlParameter("@IdPrograma", idPrograma));
            DataSet ds = DBAccess.ExecuteSPWithDS(ref cmd, "pa_consultar_misiones_programa ");
            
            foreach(DataRow dr in ds.Tables[0].Rows){
                missiones.Add(crearMission(dr, Convert.ToInt32(dr["IDMISION"])));
            }
        
            return missiones.Any()?missiones:null;
        }

        internal static IList<Mission> consultarMissionesCuerpoCeleste(int idCuerpoCeleste) {


            IList<Mission> missiones = new List<Mission>();
            SqlCommand cmd = new SqlCommand();
            cmd.Parameters.Add(new SqlParameter("@IdCuerpoCeleste", idCuerpoCeleste));
            DataSet ds = DBAccess.ExecuteSPWithDS(ref cmd, "pa_missiones_cuerpo_celeste ");

            foreach (DataRow dr in ds.Tables[0].Rows)
            {
                missiones.Add(crearMission(dr, Convert.ToInt32(dr["IDMISION"])));
            }

            return missiones.Any() ? missiones : null;
        }

    }
}
        #endregion Utilities